home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 2 / Meeting Pearls Vol. II (1995)(GTI - Schatztruhe)[!].iso / Pearls / gfx / pbm / source / jpegV5.lha / jpegV5 / src / cjpeg.c < prev    next >
C/C++ Source or Header  |  1994-12-23  |  27KB  |  878 lines

  1. /*
  2.  * cjpeg.c
  3.  *
  4.  * Copyright (C) 1991-1994, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains a command-line user interface for the JPEG compressor.
  9.  * It should work on any system with Unix- or MS-DOS-style command lines.
  10.  *
  11.  * Two different command line styles are permitted, depending on the
  12.  * compile-time switch TWO_FILE_COMMANDLINE:
  13.  *    cjpeg [options]  inputfile outputfile
  14.  *    cjpeg [options]  [inputfile]
  15.  * In the second style, output is always to standard output, which you'd
  16.  * normally redirect to a file or pipe to some other program.  Input is
  17.  * either from a named file or from standard input (typically redirected).
  18.  * The second style is convenient on Unix but is unhelpful on systems that
  19.  * don't support pipes.  Also, you MUST use the first style if your system
  20.  * doesn't do binary I/O to stdin/stdout.
  21.  * To simplify script writing, the "-outfile" switch is provided.  The syntax
  22.  *    cjpeg [options]  -outfile outputfile  inputfile
  23.  * works regardless of which command line style is used.
  24.  */
  25.  
  26. #include "cdjpeg.h"        /* Common decls for cjpeg/djpeg applications */
  27. #define JMAKE_MSG_TABLE
  28. #include "cderror.h"        /* create message string table */
  29. #include "jversion.h"        /* for version message */
  30.  
  31. #include <ctype.h>        /* to declare isupper(), tolower() */
  32. #ifdef NEED_SIGNAL_CATCHER
  33. #include <signal.h>        /* to declare signal() */
  34. #endif
  35. #ifdef USE_SETMODE
  36. #include <fcntl.h>        /* to declare setmode()'s parameter macros */
  37. /* If you have setmode() but not <io.h>, just delete this line: */
  38. #include <io.h>            /* to declare setmode() */
  39. #endif
  40.  
  41. #ifdef USE_CCOMMAND        /* command-line reader for Macintosh */
  42. #ifdef __MWERKS__
  43. #include <SIOUX.h>              /* Metrowerks declares it here */
  44. #endif
  45. #ifdef THINK_C
  46. #include <console.h>        /* Think declares it here */
  47. #endif
  48. #endif
  49.  
  50. #ifdef DONT_USE_B_MODE        /* define mode parameters for fopen() */
  51. #define READ_BINARY    "r"
  52. #define WRITE_BINARY    "w"
  53. #else
  54. #define READ_BINARY    "rb"
  55. #define WRITE_BINARY    "wb"
  56. #endif
  57.  
  58. #ifndef EXIT_FAILURE        /* define exit() codes if not provided */
  59. #define EXIT_FAILURE  1
  60. #endif
  61. #ifndef EXIT_SUCCESS
  62. #ifdef VMS
  63. #define EXIT_SUCCESS  1        /* VMS is very nonstandard */
  64. #else
  65. #define EXIT_SUCCESS  0
  66. #endif
  67. #endif
  68. #ifndef EXIT_WARNING
  69. #ifdef VMS
  70. #define EXIT_WARNING  1        /* VMS is very nonstandard */
  71. #else
  72. #define EXIT_WARNING  2
  73. #endif
  74. #endif
  75.  
  76.  
  77. /*
  78.  * This routine determines what format the input file is,
  79.  * and selects the appropriate input-reading module.
  80.  *
  81.  * To determine which family of input formats the file belongs to,
  82.  * we may look only at the first byte of the file, since C does not
  83.  * guarantee that more than one character can be pushed back with ungetc.
  84.  * Looking at additional bytes would require one of these approaches:
  85.  *     1) assume we can fseek() the input file (fails for piped input);
  86.  *     2) assume we can push back more than one character (works in
  87.  *        some C implementations, but unportable);
  88.  *     3) provide our own buffering (breaks input readers that want to use
  89.  *        stdio directly, such as the RLE library);
  90.  * or  4) don't put back the data, and modify the input_init methods to assume
  91.  *        they start reading after the start of file (also breaks RLE library).
  92.  * #1 is attractive for MS-DOS but is untenable on Unix.
  93.  *
  94.  * The most portable solution for file types that can't be identified by their
  95.  * first byte is to make the user tell us what they are.  This is also the
  96.  * only approach for "raw" file types that contain only arbitrary values.
  97.  * We presently apply this method for Targa files.  Most of the time Targa
  98.  * files start with 0x00, so we recognize that case.  Potentially, however,
  99.  * a Targa file could start with any byte value (byte 0 is the length of the
  100.  * seldom-used ID field), so we provide a switch to force Targa input mode.
  101.  */
  102.  
  103. static boolean is_targa;    /* records user -targa switch */
  104.  
  105.  
  106. LOCAL cjpeg_source_ptr
  107. select_file_type (j_compress_ptr cinfo, FILE * infile)
  108. {
  109.   int c;
  110.  
  111.   if (is_targa) {
  112. #ifdef TARGA_SUPPORTED
  113.     return jinit_read_targa(cinfo);
  114. #else
  115.     ERREXIT(cinfo, JERR_TGA_NOTCOMP);
  116. #endif
  117.   }
  118.  
  119.   if ((c = getc(infile)) == EOF)
  120.     ERREXIT(cinfo, JERR_INPUT_EMPTY);
  121.   if (ungetc(c, infile) == EOF)
  122.     ERREXIT(cinfo, JERR_UNGETC_FAILED);
  123.  
  124.   switch (c) {
  125. #ifdef BMP_SUPPORTED
  126.   case 'B':
  127.     return jinit_read_bmp(cinfo);
  128. #endif
  129. #ifdef GIF_SUPPORTED
  130.   case 'G':
  131.     return jinit_read_gif(cinfo);
  132. #endif
  133. #ifdef PPM_SUPPORTED
  134.   case 'P':
  135.     return jinit_read_ppm(cinfo);
  136. #endif
  137. #ifdef RLE_SUPPORTED
  138.   case 'R':
  139.     return jinit_read_rle(cinfo);
  140. #endif
  141. #ifdef TARGA_SUPPORTED
  142.   case 0x00:
  143.     return jinit_read_targa(cinfo);
  144. #endif
  145.   default:
  146.     ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
  147.     break;
  148.   }
  149.  
  150.   return NULL;            /* suppress compiler warnings */
  151. }
  152.  
  153.  
  154. /*
  155.  * Signal catcher to ensure that temporary files are removed before aborting.
  156.  * NB: for Amiga Manx C this is actually a global routine named _abort();
  157.  * we put "#define signal_catcher _abort" in jconfig.h.  Talk about bogus...
  158.  */
  159.  
  160. #ifdef NEED_SIGNAL_CATCHER
  161.  
  162. static j_common_ptr sig_cinfo;
  163.  
  164. GLOBAL void
  165. signal_catcher (int signum)
  166. {
  167.   if (sig_cinfo != NULL) {
  168.     if (sig_cinfo->err != NULL) /* turn off trace output */
  169.       sig_cinfo->err->trace_level = 0;
  170.     jpeg_destroy(sig_cinfo);    /* clean up memory allocation & temp files */
  171.   }
  172.   exit(EXIT_FAILURE);
  173. }
  174.  
  175. #endif
  176.  
  177.  
  178. /*
  179.  * Optional routine to display a percent-done figure on stderr.
  180.  */
  181.  
  182. #ifdef PROGRESS_REPORT
  183.  
  184. METHODDEF void
  185. progress_monitor (j_common_ptr cinfo)
  186. {
  187.   cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress;
  188.   int total_passes = prog->pub.total_passes + prog->total_extra_passes;
  189.   int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit);
  190.  
  191.   if (percent_done != prog->percent_done) {
  192.     prog->percent_done = percent_done;
  193.     if (total_passes > 1) {
  194.       fprintf(stderr, "\rPass %d/%d: %3d%% ",
  195.           prog->pub.completed_passes + prog->completed_extra_passes + 1,
  196.           total_passes, percent_done);
  197.     } else {
  198.       fprintf(stderr, "\r %3d%% ", percent_done);
  199.     }
  200.     fflush(stderr);
  201.   }
  202. }
  203.  
  204. #endif
  205.  
  206.  
  207. /*
  208.  * Argument-parsing code.
  209.  * The switch parser is designed to be useful with DOS-style command line
  210.  * syntax, ie, intermixed switches and file names, where only the switches
  211.  * to the left of a given file name affect processing of that file.
  212.  * The main program in this file doesn't actually use this capability...
  213.  */
  214.  
  215.  
  216. static const char * progname;    /* program name for error messages */
  217. static char * outfilename;    /* for -outfile switch */
  218.  
  219.  
  220. LOCAL void
  221. usage (void)
  222. /* complain about bad command line */
  223. {
  224.   fprintf(stderr, "usage: %s [switches] ", progname);
  225. #ifdef TWO_FILE_COMMANDLINE
  226.   fprintf(stderr, "inputfile outputfile\n");
  227. #else
  228.   fprintf(stderr, "[inputfile]\n");
  229. #endif
  230.  
  231.   fprintf(stderr, "Switches (names may be abbreviated):\n");
  232.   fprintf(stderr, "  -quality N     Compression quality (0..100; 5-95 is useful range)\n");
  233.   fprintf(stderr, "  -grayscale     Create monochrome JPEG file\n");
  234. #ifdef ENTROPY_OPT_SUPPORTED
  235.   fprintf(stderr, "  -optimize      Optimize Huffman table (smaller file, but slow compression)\n");
  236. #endif
  237. #ifdef TARGA_SUPPORTED
  238.   fprintf(stderr, "  -targa         Input file is Targa format (usually not needed)\n");
  239. #endif
  240.   fprintf(stderr, "Switches for advanced users:\n");
  241. #ifdef DCT_ISLOW_SUPPORTED
  242.   fprintf(stderr, "  -dct int       Use integer DCT method%s\n",
  243.       (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
  244. #endif
  245. #ifdef DCT_IFAST_SUPPORTED
  246.   fprintf(stderr, "  -dct fast      Use fast integer DCT (less accurate)%s\n",
  247.       (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
  248. #endif
  249. #ifdef DCT_FLOAT_SUPPORTED
  250.   fprintf(stderr, "  -dct float     Use floating-point DCT method%s\n",
  251.       (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
  252. #endif
  253.   fprintf(stderr, "  -restart N     Set restart interval in rows, or in blocks with B\n");
  254. #ifdef INPUT_SMOOTHING_SUPPORTED
  255.   fprintf(stderr, "  -smooth N      Smooth dithered input (N=1..100 is strength)\n");
  256. #endif
  257.   fprintf(stderr, "  -maxmemory N   Maximum memory to use (in kbytes)\n");
  258.   fprintf(stderr, "  -outfile name  Specify name for output file\n");
  259.   fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n");
  260.   fprintf(stderr, "Switches for wizards:\n");
  261. #ifdef C_ARITH_CODING_SUPPORTED
  262.   fprintf(stderr, "  -arithmetic    Use arithmetic coding\n");
  263. #endif
  264.   fprintf(stderr, "  -baseline      Force baseline output\n");
  265. #ifdef C_MULTISCAN_FILES_SUPPORTED
  266.   fprintf(stderr, "  -nointerleave  Create noninterleaved JPEG file\n");
  267. #endif
  268.   fprintf(stderr, "  -qtables file  Use quantization tables given in file\n");
  269.   fprintf(stderr, "  -qslots N[,...]    Set component quantization tables\n");
  270.   fprintf(stderr, "  -sample HxV[,...]  Set component sampling factors\n");
  271.   exit(EXIT_FAILURE);
  272. }
  273.  
  274.  
  275. LOCAL boolean
  276. keymatch (char * arg, const char * keyword, int minchars)
  277. /* Case-insensitive matching of (possibly abbreviated) keyword switches. */
  278. /* keyword is the constant keyword (must be lower case already), */
  279. /* minchars is length of minimum legal abbreviation. */
  280. {
  281.   register int ca, ck;
  282.   register int nmatched = 0;
  283.  
  284.   while ((ca = *arg++) != '\0') {
  285.     if ((ck = *keyword++) == '\0')
  286.       return FALSE;        /* arg longer than keyword, no good */
  287.     if (isupper(ca))        /* force arg to lcase (assume ck is already) */
  288.       ca = tolower(ca);
  289.     if (ca != ck)
  290.       return FALSE;        /* no good */
  291.     nmatched++;            /* count matched characters */
  292.   }
  293.   /* reached end of argument; fail if it's too short for unique abbrev */
  294.   if (nmatched < minchars)
  295.     return FALSE;
  296.   return TRUE;            /* A-OK */
  297. }
  298.  
  299.  
  300. LOCAL int
  301. qt_getc (FILE * file)
  302. /* Read next char, skipping over any comments (# to end of line) */
  303. /* A comment/newline sequence is returned as a newline */
  304. {
  305.   register int ch;
  306.   
  307.   ch = getc(file);
  308.   if (ch == '#') {
  309.     do {
  310.       ch = getc(file);
  311.     } while (ch != '\n' && ch != EOF);
  312.   }
  313.   return ch;
  314. }
  315.  
  316.  
  317. LOCAL long
  318. read_qt_integer (FILE * file)
  319. /* Read an unsigned decimal integer from a quantization-table file */
  320. /* Swallows one trailing character after the integer */
  321. {
  322.   register int ch;
  323.   register long val;
  324.   
  325.   /* Skip any leading whitespace, detect EOF */
  326.   do {
  327.     ch = qt_getc(file);
  328.     if (ch == EOF)
  329.       return EOF;
  330.   } while (isspace(ch));
  331.   
  332.   if (! isdigit(ch)) {
  333.     fprintf(stderr, "%s: bogus data in quantization file\n", progname);
  334.     exit(EXIT_FAILURE);
  335.   }
  336.  
  337.   val = ch - '0';
  338.   while (ch = qt_getc(file), isdigit(ch)) {
  339.     val *= 10;
  340.     val += ch - '0';
  341.   }
  342.   return val;
  343. }
  344.  
  345.  
  346. LOCAL void
  347. read_quant_tables (j_compress_ptr cinfo, char * filename, int scale_factor,
  348.            boolean force_baseline)
  349. /* Read a set of quantization tables from the specified file.
  350.  * The file is plain ASCII text: decimal numbers with whitespace between.
  351.  * Comments preceded by '#' may be included in the file.
  352.  * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
  353.  * The tables are implicitly numbered 0,1,etc.
  354.  * NOTE: does not affect the qslots mapping, which will default to selecting
  355.  * table 0 for luminance (or primary) components, 1 for chrominance components.
  356.  * You must use -qslots if you want a different component->table mapping.
  357.  */
  358. {
  359.   /* ZIG[i] is the zigzag-order position of the i'th element of a DCT block */
  360.   /* read in natural order (left to right, top to bottom). */
  361.   static const int ZIG[DCTSIZE2] = {
  362.      0,  1,  5,  6, 14, 15, 27, 28,
  363.      2,  4,  7, 13, 16, 26, 29, 42,
  364.      3,  8, 12, 17, 25, 30, 41, 43,
  365.      9, 11, 18, 24, 31, 40, 44, 53,
  366.     10, 19, 23, 32, 39, 45, 52, 54,
  367.     20, 22, 33, 38, 46, 51, 55, 60,
  368.     21, 34, 37, 47, 50, 56, 59, 61,
  369.     35, 36, 48, 49, 57, 58, 62, 63
  370.     };
  371.   FILE * fp;
  372.   int tblno, i;
  373.   long val;
  374.   unsigned int table[DCTSIZE2];
  375.  
  376.   if ((fp = fopen(filename, "r")) == NULL) {
  377.     fprintf(stderr, "%s: can't open %s\n", progname, filename);
  378.     exit(EXIT_FAILURE);
  379.   }
  380.   tblno = 0;
  381.  
  382.   while ((val = read_qt_integer(fp)) != EOF) { /* read 1st element of table */
  383.     if (tblno >= NUM_QUANT_TBLS) {
  384.       fprintf(stderr, "%s: too many tables in file %s\n", progname, filename);
  385.       exit(EXIT_FAILURE);
  386.     }
  387.     table[0] = (unsigned int) val;
  388.     for (i = 1; i < DCTSIZE2; i++) {
  389.       if ((val = read_qt_integer(fp)) == EOF) {
  390.     fprintf(stderr, "%s: incomplete table in file %s\n", progname, filename);
  391.     exit(EXIT_FAILURE);
  392.       }
  393.       table[ZIG[i]] = (unsigned int) val;
  394.     }
  395.     jpeg_add_quant_table(cinfo, tblno, table, scale_factor, force_baseline);
  396.     tblno++;
  397.   }
  398.  
  399.   fclose(fp);
  400. }
  401.  
  402.  
  403. LOCAL void
  404. set_quant_slots (j_compress_ptr cinfo, char *arg)
  405. /* Process a quantization-table-selectors parameter string, of the form
  406.  *     N[,N,...]
  407.  * If there are more components than parameters, the last value is replicated.
  408.  */
  409. {
  410.   int val = 0;            /* default table # */
  411.   int ci;
  412.   char ch;
  413.  
  414.   for (ci = 0; ci < MAX_COMPONENTS; ci++) {
  415.     if (*arg) {
  416.       ch = ',';            /* if not set by sscanf, will be ',' */
  417.       if (sscanf(arg, "%d%c", &val, &ch) < 1)
  418.     usage();
  419.       if (ch != ',')
  420.     usage();        /* syntax check */
  421.       if (val < 0 || val >= NUM_QUANT_TBLS) {
  422.     fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n",
  423.         NUM_QUANT_TBLS-1);
  424.     exit(EXIT_FAILURE);
  425.       }
  426.       cinfo->comp_info[ci].quant_tbl_no = val;
  427.       while (*arg && *arg++ != ',') /* advance to next segment of arg string */
  428.     ;
  429.     } else {
  430.       /* reached end of parameter, set remaining components to last table */
  431.       cinfo->comp_info[ci].quant_tbl_no = val;
  432.     }
  433.   }
  434. }
  435.  
  436.  
  437. LOCAL void
  438. set_sample_factors (j_compress_ptr cinfo, char *arg)
  439. /* Process a sample-factors parameter string, of the form
  440.  *     HxV[,HxV,...]
  441.  * If there are more components than parameters, "1x1" is assumed.
  442.  */
  443. {
  444.   int ci, val1, val2;
  445.   char ch1, ch2;
  446.  
  447.   for (ci = 0; ci < MAX_COMPONENTS; ci++) {
  448.     if (*arg) {
  449.       ch2 = ',';        /* if not set by sscanf, will be ',' */
  450.       if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
  451.     usage();
  452.       if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',')
  453.     usage();        /* syntax check */
  454.       if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) {
  455.     fprintf(stderr, "JPEG sampling factors must be 1..4\n");
  456.     exit(EXIT_FAILURE);
  457.       }
  458.       cinfo->comp_info[ci].h_samp_factor = val1;
  459.       cinfo->comp_info[ci].v_samp_factor = val2;
  460.       while (*arg && *arg++ != ',') /* advance to next segment of arg string */
  461.     ;
  462.     } else {
  463.       /* reached end of parameter, set remaining components to 1x1 sampling */
  464.       cinfo->comp_info[ci].h_samp_factor = 1;
  465.       cinfo->comp_info[ci].v_samp_factor = 1;
  466.     }
  467.   }
  468. }
  469.  
  470.  
  471. LOCAL int
  472. parse_switches (j_compress_ptr cinfo, int argc, char **argv,
  473.         int last_file_arg_seen, boolean for_real)
  474. /* Parse optional switches.
  475.  * Returns argv[] index of first file-name argument (== argc if none).
  476.  * Any file names with indexes <= last_file_arg_seen are ignored;
  477.  * they have presumably been processed in a previous iteration.
  478.  * (Pass 0 for last_file_arg_seen on the first or only iteration.)
  479.  * for_real is FALSE on the first (dummy) pass; we may skip any expensive
  480.  * processing.
  481.  */
  482. {
  483.   int argn;
  484.   char * arg;
  485.   int quality;            /* -quality parameter */
  486.   int q_scale_factor;        /* scaling percentage for -qtables */
  487.   boolean force_baseline;
  488.   char * qtablefile = NULL;    /* saves -qtables filename if any */
  489.   char * qslotsarg = NULL;    /* saves -qslots parm if any */
  490.   char * samplearg = NULL;    /* saves -sample parm if any */
  491.  
  492.   /* Set up default JPEG parameters. */
  493.   /* Note that default -quality level need not, and does not,
  494.    * match the default scaling for an explicit -qtables argument.
  495.    */
  496.   quality = 75;            /* default -quality value */
  497.   q_scale_factor = 100;        /* default to no scaling for -qtables */
  498.   force_baseline = FALSE;    /* by default, allow 16-bit quantizers */
  499.   is_targa = FALSE;
  500.   outfilename = NULL;
  501.   cinfo->err->trace_level = 0;
  502.  
  503.   /* Scan command line options, adjust parameters */
  504.  
  505.   for (argn = 1; argn < argc; argn++) {
  506.     arg = argv[argn];
  507.     if (*arg != '-') {
  508.       /* Not a switch, must be a file name argument */
  509.       if (argn <= last_file_arg_seen) {
  510.     outfilename = NULL;    /* -outfile applies to just one input file */
  511.     continue;        /* ignore this name if previously processed */
  512.       }
  513.       break;            /* else done parsing switches */
  514.     }
  515.     arg++;            /* advance past switch marker character */
  516.  
  517.     if (keymatch(arg, "arithmetic", 1)) {
  518.       /* Use arithmetic coding. */
  519. #ifdef C_ARITH_CODING_SUPPORTED
  520.       cinfo->arith_code = TRUE;
  521. #else
  522.       fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
  523.           progname);
  524.       exit(EXIT_FAILURE);
  525. #endif
  526.  
  527.     } else if (keymatch(arg, "baseline", 1)) {
  528.       /* Force baseline output (8-bit quantizer values). */
  529.       force_baseline = TRUE;
  530.  
  531.     } else if (keymatch(arg, "dct", 2)) {
  532.       /* Select DCT algorithm. */
  533.       if (++argn >= argc)    /* advance to next argument */
  534.     usage();
  535.       if (keymatch(argv[argn], "int", 1)) {
  536.     cinfo->dct_method = JDCT_ISLOW;
  537.       } else if (keymatch(argv[argn], "fast", 2)) {
  538.     cinfo->dct_method = JDCT_IFAST;
  539.       } else if (keymatch(argv[argn], "float", 2)) {
  540.     cinfo->dct_method = JDCT_FLOAT;
  541.       } else
  542.     usage();
  543.  
  544.     } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
  545.       /* Enable debug printouts. */
  546.       /* On first -d, print version identification */
  547.       static boolean printed_version = FALSE;
  548.  
  549.       if (! printed_version) {
  550.     fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
  551.         JVERSION, JCOPYRIGHT);
  552.     printed_version = TRUE;
  553.       }
  554.       cinfo->err->trace_level++;
  555.  
  556.     } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
  557.       /* Force a monochrome JPEG file to be generated. */
  558.       jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
  559.  
  560.     } else if (keymatch(arg, "maxmemory", 3)) {
  561.       /* Maximum memory in Kb (or Mb with 'm'). */
  562.       long lval;
  563.       char ch = 'x';
  564.  
  565.       if (++argn >= argc)    /* advance to next argument */
  566.     usage();
  567.       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  568.     usage();
  569.       if (ch == 'm' || ch == 'M')
  570.     lval *= 1000L;
  571.       cinfo->mem->max_memory_to_use = lval * 1000L;
  572.  
  573.     } else if (keymatch(arg, "nointerleave", 3)) {
  574.       /* Create noninterleaved file. */
  575. #ifdef C_MULTISCAN_FILES_SUPPORTED
  576.       cinfo->interleave = FALSE;
  577. #else
  578.       fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n",
  579.           progname);
  580.       exit(EXIT_FAILURE);
  581. #endif
  582.  
  583.     } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
  584.       /* Enable entropy parm optimization. */
  585. #ifdef ENTROPY_OPT_SUPPORTED
  586.       cinfo->optimize_coding = TRUE;
  587. #else
  588.       fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
  589.           progname);
  590.       exit(EXIT_FAILURE);
  591. #endif
  592.  
  593.     } else if (keymatch(arg, "outfile", 4)) {
  594.       /* Set output file name. */
  595.       if (++argn >= argc)    /* advance to next argument */
  596.     usage();
  597.       outfilename = argv[argn];    /* save it away for later use */
  598.  
  599.     } else if (keymatch(arg, "quality", 1)) {
  600.       /* Quality factor (quantization table scaling factor). */
  601.       if (++argn >= argc)    /* advance to next argument */
  602.     usage();
  603.       if (sscanf(argv[argn], "%d", &quality) != 1)
  604.     usage();
  605.       /* Change scale factor in case -qtables is present. */
  606.       q_scale_factor = jpeg_quality_scaling(quality);
  607.  
  608.     } else if (keymatch(arg, "qslots", 2)) {
  609.       /* Quantization table slot numbers. */
  610.       if (++argn >= argc)    /* advance to next argument */
  611.     usage();
  612.       qslotsarg = argv[argn];
  613.       /* Must delay setting qslots until after we have processed any
  614.        * colorspace-determining switches, since jpeg_set_colorspace sets
  615.        * default quant table numbers.
  616.        */
  617.  
  618.     } else if (keymatch(arg, "qtables", 2)) {
  619.       /* Quantization tables fetched from file. */
  620.       if (++argn >= argc)    /* advance to next argument */
  621.     usage();
  622.       qtablefile = argv[argn];
  623.       /* We postpone actually reading the file in case -quality comes later. */
  624.  
  625.     } else if (keymatch(arg, "restart", 1)) {
  626.       /* Restart interval in MCU rows (or in MCUs with 'b'). */
  627.       long lval;
  628.       char ch = 'x';
  629.  
  630.       if (++argn >= argc)    /* advance to next argument */
  631.     usage();
  632.       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  633.     usage();
  634.       if (lval < 0 || lval > 65535L)
  635.     usage();
  636.       if (ch == 'b' || ch == 'B') {
  637.     cinfo->restart_interval = (unsigned int) lval;
  638.     cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
  639.       } else {
  640.     cinfo->restart_in_rows = (int) lval;
  641.     /* restart_interval will be computed during startup */
  642.       }
  643.  
  644.     } else if (keymatch(arg, "sample", 2)) {
  645.       /* Set sampling factors. */
  646.       if (++argn >= argc)    /* advance to next argument */
  647.     usage();
  648.       samplearg = argv[argn];
  649.       /* Must delay setting sample factors until after we have processed any
  650.        * colorspace-determining switches, since jpeg_set_colorspace sets
  651.        * default sampling factors.
  652.        */
  653.  
  654.     } else if (keymatch(arg, "smooth", 2)) {
  655.       /* Set input smoothing factor. */
  656.       int val;
  657.  
  658.       if (++argn >= argc)    /* advance to next argument */
  659.     usage();
  660.       if (sscanf(argv[argn], "%d", &val) != 1)
  661.     usage();
  662.       if (val < 0 || val > 100)
  663.     usage();
  664.       cinfo->smoothing_factor = val;
  665.  
  666.     } else if (keymatch(arg, "targa", 1)) {
  667.       /* Input file is Targa format. */
  668.       is_targa = TRUE;
  669.  
  670.     } else {
  671.       usage();            /* bogus switch */
  672.     }
  673.   }
  674.  
  675.   /* Post-switch-scanning cleanup */
  676.  
  677.   if (for_real) {
  678.  
  679.     /* Set quantization tables for selected quality. */
  680.     /* Some or all may be overridden if -qtables is present. */
  681.     jpeg_set_quality(cinfo, quality, force_baseline);
  682.  
  683.     if (qtablefile != NULL)    /* process -qtables if it was present */
  684.       read_quant_tables(cinfo, qtablefile, q_scale_factor, force_baseline);
  685.  
  686.     if (qslotsarg != NULL)    /* process -qslots if it was present */
  687.       set_quant_slots(cinfo, qslotsarg);
  688.  
  689.     if (samplearg != NULL)    /* process -sample if it was present */
  690.       set_sample_factors(cinfo, samplearg);
  691.  
  692.   }
  693.  
  694.   return argn;            /* return index of next arg (file name) */
  695. }
  696.  
  697.  
  698. /*
  699.  * The main program.
  700.  */
  701.  
  702. GLOBAL int
  703. main (int argc, char **argv)
  704. {
  705.   struct jpeg_compress_struct cinfo;
  706.   struct jpeg_error_mgr jerr;
  707. #ifdef PROGRESS_REPORT
  708.   struct cdjpeg_progress_mgr progress;
  709. #endif
  710.   int file_index;
  711.   cjpeg_source_ptr src_mgr;
  712.   FILE * input_file;
  713.   FILE * output_file;
  714.   JDIMENSION num_scanlines;
  715.  
  716.   /* On Mac, fetch a command line. */
  717. #ifdef USE_CCOMMAND
  718.   argc = ccommand(&argv);
  719. #endif
  720.  
  721.   progname = argv[0];
  722.   if (progname == NULL || progname[0] == 0)
  723.     progname = "cjpeg";        /* in case C library doesn't provide it */
  724.  
  725.   /* Initialize the JPEG compression object with default error handling. */
  726.   cinfo.err = jpeg_std_error(&jerr);
  727.   jpeg_create_compress(&cinfo);
  728.   /* Add some application-specific error messages (from cderror.h) */
  729.   jerr.addon_message_table = addon_message_table;
  730.   jerr.first_addon_message = JMSG_FIRSTADDONCODE;
  731.   jerr.last_addon_message = JMSG_LASTADDONCODE;
  732.  
  733.   /* Now safe to enable signal catcher. */
  734. #ifdef NEED_SIGNAL_CATCHER
  735.   sig_cinfo = (j_common_ptr) &cinfo;
  736.   signal(SIGINT, signal_catcher);
  737. #ifdef SIGTERM            /* not all systems have SIGTERM */
  738.   signal(SIGTERM, signal_catcher);
  739. #endif
  740. #endif
  741.  
  742.   /* Initialize JPEG parameters.
  743.    * Much of this may be overridden later.
  744.    * In particular, we don't yet know the input file's color space,
  745.    * but we need to provide some value for jpeg_set_defaults() to work.
  746.    */
  747.  
  748.   cinfo.in_color_space = JCS_RGB; /* arbitrary guess */
  749.   jpeg_set_defaults(&cinfo);
  750.  
  751.   /* Scan command line to find file names.
  752.    * It is convenient to use just one switch-parsing routine, but the switch
  753.    * values read here are ignored; we will rescan the switches after opening
  754.    * the input file.
  755.    */
  756.  
  757.   file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
  758.  
  759. #ifdef TWO_FILE_COMMANDLINE
  760.   /* Must have either -outfile switch or explicit output file name */
  761.   if (outfilename == NULL) {
  762.     if (file_index != argc-2) {
  763.       fprintf(stderr, "%s: must name one input and one output file\n",
  764.           progname);
  765.       usage();
  766.     }
  767.     outfilename = argv[file_index+1];
  768.   } else {
  769.     if (file_index != argc-1) {
  770.       fprintf(stderr, "%s: must name one input and one output file\n",
  771.           progname);
  772.       usage();
  773.     }
  774.   }
  775. #else
  776.   /* Unix style: expect zero or one file name */
  777.   if (file_index < argc-1) {
  778.     fprintf(stderr, "%s: only one input file\n", progname);
  779.     usage();
  780.   }
  781. #endif /* TWO_FILE_COMMANDLINE */
  782.  
  783.   /* Open the input file. */
  784.   if (file_index < argc) {
  785.     if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
  786.       fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
  787.       exit(EXIT_FAILURE);
  788.     }
  789.   } else {
  790.     /* default input file is stdin */
  791. #ifdef USE_SETMODE        /* need to hack file mode? */
  792.     setmode(fileno(stdin), O_BINARY);
  793. #endif
  794. #ifdef USE_FDOPEN        /* need to re-open in binary mode? */
  795.     if ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
  796.       fprintf(stderr, "%s: can't open stdin\n", progname);
  797.       exit(EXIT_FAILURE);
  798.     }
  799. #else
  800.     input_file = stdin;
  801. #endif
  802.   }
  803.  
  804.   /* Open the output file. */
  805.   if (outfilename != NULL) {
  806.     if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
  807.       fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
  808.       exit(EXIT_FAILURE);
  809.     }
  810.   } else {
  811.     /* default output file is stdout */
  812. #ifdef USE_SETMODE        /* need to hack file mode? */
  813.     setmode(fileno(stdout), O_BINARY);
  814. #endif
  815. #ifdef USE_FDOPEN        /* need to re-open in binary mode? */
  816.     if ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
  817.       fprintf(stderr, "%s: can't open stdout\n", progname);
  818.       exit(EXIT_FAILURE);
  819.     }
  820. #else
  821.     output_file = stdout;
  822. #endif
  823.   }
  824.  
  825. #ifdef PROGRESS_REPORT
  826.   /* Enable progress display, unless trace output is on */
  827.   if (jerr.trace_level == 0) {
  828.     progress.pub.progress_monitor = progress_monitor;
  829.     progress.completed_extra_passes = 0;
  830.     progress.total_extra_passes = 0;
  831.     progress.percent_done = -1;
  832.     cinfo.progress = &progress.pub;
  833.   }
  834. #endif
  835.  
  836.   /* Figure out the input file format, and set up to read it. */
  837.   src_mgr = select_file_type(&cinfo, input_file);
  838.   src_mgr->input_file = input_file;
  839.  
  840.   /* Read the input file header to obtain file size & colorspace. */
  841.   (*src_mgr->start_input) (&cinfo, src_mgr);
  842.  
  843.   /* Now that we know input colorspace, fix colorspace-dependent defaults */
  844.   jpeg_default_colorspace(&cinfo);
  845.  
  846.   /* Adjust default compression parameters by re-parsing the options */
  847.   file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
  848.  
  849.   /* Specify data destination for compression */
  850.   jpeg_stdio_dest(&cinfo, output_file);
  851.  
  852.   /* Start compressor */
  853.   jpeg_start_compress(&cinfo, TRUE);
  854.  
  855.   /* Process data */
  856.   while (cinfo.next_scanline < cinfo.image_height) {
  857.     num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
  858.     (void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
  859.   }
  860.  
  861.   /* Finish compression and release memory */
  862.   (*src_mgr->finish_input) (&cinfo, src_mgr);
  863.   jpeg_finish_compress(&cinfo);
  864.   jpeg_destroy_compress(&cinfo);
  865.  
  866. #ifdef PROGRESS_REPORT
  867.   /* Clear away progress display */
  868.   if (jerr.trace_level == 0) {
  869.     fprintf(stderr, "\r                \r");
  870.     fflush(stderr);
  871.   }
  872. #endif
  873.  
  874.   /* All done. */
  875.   exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
  876.   return 0;            /* suppress no-return-value warnings */
  877. }
  878.